# -*- coding: utf-8 -*-
from flask import Blueprint, g
from sqlalchemy import func, or_
from common.response import success, error
from common.error_code import ErrorCode
from dao.exam_dao import Exam, Score
from dao.group_dao import StudyGroup
from filter.auth import auth_required
from filter.decorators import require_role, validate_request
from dao.db import db
from dao.user_dao import Student, Teacher, User, Class
from dao.class_dao import ClassSubjectTeacher
from dao.message_dao import Message
from model.request import StudentDetailRequest

# 用户相关蓝图
user_bp = Blueprint('user', __name__, url_prefix='/api/user')

@user_bp.route('/teacher/info', methods=['POST'])
@auth_required
@require_role(['admin', 'teacher'])
def get_teacher_info():
    """获取教师基本信息接口（修正班主任兼任任课老师逻辑）"""
    # 获取当前用户ID
    current_user_id = g.user_id
    
    # 1. 查询教师基本信息
    teacher = db.session.query(
        Teacher,
        User
    ).join(
        User, Teacher.user_id == User.id
    ).filter(
        Teacher.user_id == current_user_id
    ).first()
    
    if not teacher:
        return error(ErrorCode.NOT_FOUND, "教师信息不存在")
    
    teacher_info, user_info = teacher
    teacher_id = teacher_info.id  # 教师在teachers表中的ID
    
    # 2. 查询负责的班级列表（班主任 + 任课老师）
    responsible_classes = []
    processed_class_ids = set()  # 用于跟踪已处理的班级ID
    
    # 2.1 先处理作为班主任的班级
    head_teacher_classes = db.session.query(Class).filter(
        Class.head_teacher_id == teacher_id
    ).all()
    
    for cls in head_teacher_classes:
        processed_class_ids.add(cls.id)
        
        # 获取当前教师在该班级担任的科目
        taught_subjects = db.session.query(ClassSubjectTeacher.subject).filter(
            ClassSubjectTeacher.class_id == cls.id,
            ClassSubjectTeacher.teacher_id == teacher_id
        ).distinct().all()
        
        # 获取该班级的所有任课科目
        all_subjects = db.session.query(ClassSubjectTeacher.subject).filter(
            ClassSubjectTeacher.class_id == cls.id
        ).distinct().all()
        
        responsible_classes.append({
            "class_id": cls.id,
            "class_name": cls.name,
            "grade": cls.grade,
            "subjects": [s[0] for s in all_subjects],  # 班级所有科目
            "taught_subjects": [s[0] for s in taught_subjects],  # 教师任教科目
            "is_head_teacher": True
        })
    
    # 2.2 处理作为任课老师的班级（包括班主任所在班级）
    subject_teacher_relations = db.session.query(
        ClassSubjectTeacher,
        Class
    ).join(
        Class, ClassSubjectTeacher.class_id == Class.id
    ).filter(
        ClassSubjectTeacher.teacher_id == teacher_id
    ).all()
    
    for relation, cls in subject_teacher_relations:
        # 如果是已处理的班级（班主任班级），更新任教科目信息
        if cls.id in processed_class_ids:
            for class_item in responsible_classes:
                if class_item["class_id"] == cls.id:
                    # 确保科目不重复
                    if relation.subject not in class_item["taught_subjects"]:
                        class_item["taught_subjects"].append(relation.subject)
            continue
        
        # 新班级，添加到列表
        processed_class_ids.add(cls.id)
        
        # 获取该班级的所有任课科目
        all_subjects = db.session.query(ClassSubjectTeacher.subject).filter(
            ClassSubjectTeacher.class_id == cls.id
        ).distinct().all()
        
        responsible_classes.append({
            "class_id": cls.id,
            "class_name": cls.name,
            "grade": cls.grade,
            "subjects": [s[0] for s in all_subjects],  # 班级所有科目
            "taught_subjects": [relation.subject],  # 教师任教科目
            "is_head_teacher": False
        })
    
    # 3. 查询未读留言数量
    unread_count = Message.query.filter(
        Message.receiver_id == teacher_id,
        Message.receiver_role.in_(['teacher', 'admin']),
        Message.is_read == False
    ).count()
    
    # 4. 整理返回结果
    return success({
        "username": user_info.username,
        "name": user_info.name,
        "role": user_info.role,
        "position": teacher_info.position or "",
        "responsible_classes": responsible_classes,
        "unread_message_count": unread_count
    })

@user_bp.route('/student/info', methods=['POST'])
@auth_required
@validate_request(StudentDetailRequest)
def get_student_detail():
    """获取学生详细信息接口"""
    data: StudentDetailRequest = g.request_data
    current_role = g.role
    
    # 1. 确定要查询的学生ID
    target_student_id = None
    
    if current_role in ['admin', 'teacher']:
        # 管理员和教师必须提供学生ID
        if not data.student_id:
            return error(ErrorCode.INVALID_PARAM, "学生ID不能为空")
        target_student_id = data.student_id
    else:  # student角色
        # 学生只能查询自己的信息，忽略传入的student_id
        current_user_id = g.user_id
        student = Student.query.filter_by(user_id=current_user_id).first()
        if not student:
            return error(ErrorCode.NOT_FOUND, "学生信息不存在")
        target_student_id = student.id
    
    # 2. 查询学生基本信息
    student_info = db.session.query(
        Student,
        User,
        Class
    ).join(
        User, Student.user_id == User.id
    ).join(
        Class, Student.class_id == Class.id
    ).filter(
        Student.id == target_student_id
    ).first()
    
    if not student_info:
        return error(ErrorCode.NOT_FOUND, f"ID为{target_student_id}的学生不存在")
    
    student, user, cls = student_info
    
    # 3. 获取学生行为规范积分总数
    total_points = student.performance_points
    
    # 4. 计算学生积分在班级中的排名（处理并列情况）
    class_rank = calculate_student_class_rank(cls.id, total_points)
    
    # 5. 获取小组信息（如果存在）
    group_info = None
    if student.group_id:
        group = StudyGroup.query.get(student.group_id)
        if group:
            # 计算小组总积分
            group_total = calculate_group_total_points(cls.id, group.id)
            
            # 计算小组在班级中的排名
            group_rank = calculate_group_class_rank(cls.id, group_total)
            
            group_info = {
                "group_id": group.id,
                "group_name": group.name,
                "group_total_points": group_total,
                "group_rank": group_rank
            }
    
    # 6. 计算未到截止日期但未录入成绩的考试数量
    pending_exams_count = db.session.query(func.count(Exam.id)).filter(
        # 考试属于学生所在班级或年级
        or_(
            Exam.class_id == cls.id,
            Exam.grade == cls.grade
        ),
        # 考试截止日期未到
        Exam.deadline > func.now(),
        # 学生未录入该考试成绩
        ~Exam.id.in_(
            db.session.query(Score.exam_id).filter(
                Score.student_id == student.id
            )
        )
    ).scalar() or 0
    
    # 7. 计算未读留言数量
    unread_message_count = Message.query.filter(
        Message.receiver_id == student.id,
        Message.receiver_role == 'student',
        Message.is_read == False
    ).count()
    
    # 8. 整理返回结果
    result = {
        "username": user.username,
        "student_name": user.name,
        "class_id": cls.id,
        "class_name": cls.name,
        "grade": cls.grade,
        "student_id": student.student_id,  # 学号
        "performance_points": total_points,  # 行为规范积分总数
        "class_rank": class_rank,  # 积分班级排名
        "unread_message_count": unread_message_count,  # 未读留言数量
        "pending_exams_count": pending_exams_count  # 未完成考试数量
    }
    
    # 添加小组信息（如果存在）
    if group_info:
        result.update({
            "group_id": group_info["group_id"],
            "group_name": group_info["group_name"],
            "group_total_points": group_info["group_total_points"],
            "group_rank": group_info["group_rank"]
        })
    
    return success(result)

# 辅助函数：计算学生在班级中的排名（处理并列情况）
def calculate_student_class_rank(class_id, student_points):
    # 获取班级内所有学生的积分，按降序排列
    class_students = Student.query.filter_by(class_id=class_id).all()
    scores = sorted([s.performance_points for s in class_students], reverse=True)
    
    if not scores:
        return 0
        
    # 处理并列排名逻辑
    rank = 1
    prev_score = scores[0]
    
    # 如果当前学生是最高分，直接返回第1名
    if student_points == prev_score:
        return rank
        
    # 遍历所有分数计算排名
    for i in range(1, len(scores)):
        # 分数变化时，更新排名为当前索引+1
        if scores[i] != prev_score:
            rank = i + 1
            prev_score = scores[i]
            
        # 找到当前学生的分数，返回对应的排名
        if scores[i] == student_points:
            return rank
            
    # 如果未找到（理论上不可能），返回最后一名
    return len(scores)

# 辅助函数：计算小组的总积分
def calculate_group_total_points(class_id, group_id):
    # 获取小组内所有学生
    group_students = Student.query.filter_by(
        class_id=class_id,
        group_id=group_id
    ).all()
    
    # 计算所有学生积分总和
    return sum(s.performance_points for s in group_students)

# 辅助函数：计算小组在班级中的排名（处理并列情况）
def calculate_group_class_rank(class_id, group_total):
    # 获取班级内所有小组及其总积分
    groups = StudyGroup.query.filter_by(class_id=class_id).all()
    group_totals = []
    
    for group in groups:
        total = calculate_group_total_points(class_id, group.id)
        group_totals.append(total)
    
    # 按积分降序排列
    sorted_totals = sorted(group_totals, reverse=True)
    
    if not sorted_totals:
        return 0
        
    # 处理并列排名逻辑
    rank = 1
    prev_total = sorted_totals[0]
    
    # 如果当前小组是最高分，直接返回第1名
    if group_total == prev_total:
        return rank
        
    # 遍历所有小组积分计算排名
    for i in range(1, len(sorted_totals)):
        # 积分变化时，更新排名为当前索引+1
        if sorted_totals[i] != prev_total:
            rank = i + 1
            prev_total = sorted_totals[i]
            
        # 找到当前小组的积分，返回对应的排名
        if sorted_totals[i] == group_total:
            return rank
            
    # 如果未找到（理论上不可能），返回最后一名
    return len(sorted_totals)